""" 
测试方法
stress --cpu 1

获取stess pid


百分比计算方法:
https://www.cnblogs.com/liushui-sky/p/9236007.html
"""
import os
import time
from enum import IntEnum
from dataclasses import dataclass
import multiprocessing

@dataclass
class proc_stat_data:
    pid: int = 0
    comm: str = ""
    state: str = ""
    ppid: int = 0
    pgrp: int = 0
    session: int = 0
    tty_nr: int = 0
    tpgid: int = 0
    flags: int = 0
    minflt: int = 0
    cminflt: int = 0
    majflt: int = 0
    cmajflt: int = 0
    utime: int = 0
    stime: int = 0
    cutime: int = 0
    cstime: int = 0
    priority: int = 0
    nice: int = 0
    num_threads: int = 0
    itrealvalue: int = 0
    starttime: int = 0
    vsize: int = 0
    rss: int = 0


@dataclass
class cpu_stat_data:
    user: int = 0
    nice: int = 0
    system: int = 0
    idle: int = 0
    iowait: int = 0
    irq: int = 0
    softirq: int = 0
    steal: int = 0
    guest: int = 0
    total: int = 0


class proc_stat_opt:
    def __init__(self):
        self.cpu_num = multiprocessing.cpu_count()

    def get_proc_stat(self, pid):
        file = f"/proc/{pid}/stat"
        if not os.path.exists(file):
            return None
        # 读取/proc/[pid]/stat文件
        with open(f"/proc/{pid}/stat", "r") as f:
            stat_str = f.read()
        # 解析stat文件内容
        stat_list = stat_str.split()
        data = proc_stat_data()
        data.comm = stat_list[1][1:-1]
        data.state = stat_list[2]
        data.ppid = int(stat_list[3])
        data.pgrp = int(stat_list[4])
        data.session = int(stat_list[5])
        data.tty_nr = int(stat_list[6])
        data.tpgid = int(stat_list[7])
        data.flags = int(stat_list[8])
        data.minflt = int(stat_list[9])
        data.cminflt = int(stat_list[10])
        data.majflt = int(stat_list[11])
        data.cmajflt = int(stat_list[12])
        data.utime = int(stat_list[13])
        data.stime = int(stat_list[14])
        data.cutime = int(stat_list[15])
        data.cstime = int(stat_list[16])
        data.priority = int(stat_list[17])
        data.nice = int(stat_list[18])
        data.num_threads = int(stat_list[19])
        data.itrealvalue = int(stat_list[20])
        data.starttime = int(stat_list[21])
        data.vsize = int(stat_list[22])
        data.rss = int(stat_list[23])
        # 返回data对象
        return data

    def get_system_cpu_stat(self):
        with open("/proc/stat", "r") as f:
            cpu_stat_line = f.readline().split()
            cpu_stat = cpu_stat_data()
            cpu_stat.user = int(cpu_stat_line[1])
            cpu_stat.nice = int(cpu_stat_line[2])
            cpu_stat.system = int(cpu_stat_line[3])
            cpu_stat.idle = int(cpu_stat_line[4])
            cpu_stat.iowait = int(cpu_stat_line[5])
            cpu_stat.irq = int(cpu_stat_line[6])
            cpu_stat.softirq = int(cpu_stat_line[7])
            cpu_stat.steal = int(cpu_stat_line[8])
            cpu_stat.guest = int(cpu_stat_line[9])

            data = [int(x) for x in cpu_stat_line[1:10]]
            cpu_stat.total = sum(data)
            return cpu_stat


    def cal_process_cpu_usage(self,pid,interval=1):
        cpu_time1 = self.get_system_cpu_stat()
        proc_data = self.get_proc_stat(pid)
        proc_time1 = proc_data.utime + proc_data.stime + proc_data.cutime + proc_data.cstime

        time.sleep(interval)

        cpu_time2 = self.get_system_cpu_stat()
        proc_data = self.get_proc_stat(pid)
        proc_time2 = proc_data.utime + proc_data.stime + proc_data.cutime + proc_data.cstime
        
        pcpu=100*self.cpu_num*(proc_time2-proc_time1)/(cpu_time2.total-cpu_time1.total)
        print("pid cpu usage: ",pcpu)
        
        

if __name__ == "__main__":
    opt = proc_stat_opt()
    data = opt.get_proc_stat(1)
    cpu_stat = opt.get_system_cpu_stat()
    print(data)

    # 监控进程, 改为监控的进程pid
    pid = 199846
    while True:
        opt.cal_process_cpu_usage(pid,interval=1)
        time.sleep(1)